介绍nginx中location块的匹配符(~, ~*, ^~, [space]等)与alias文件代理的关系

实验环境

静态资源目录

E: /static

  • a.js
  • b.js
  • /case/

    • c.js
    • d.js
    • e.js
nginx server块
server {
    listen       80;
    server_name  127.0.0.1;
}

alias代理特定文件

仅仅代理一个特定的文件,基本上很少会出错,
location块是前缀匹配和正则匹配均可。
如下,浏览器访问http://127.0.0.1/static/case/... 都返回c.js的内容。

    location /static/case/c.js {
        alias E:/static/case/c.js;
    }
    location ~ /static/case/c.js {
        alias E:/static/case/c.js;
    }

alias代理某目录下的各个文件

但当需要代理一个目录下的各个文件时,会因location块是前缀匹配和正则匹配的不同,导致代理的结果不同。
尤其是location是正则匹配时,较为特殊,容易出错。

location是前缀匹配^~或者[space]时

这种情况如果出错,一般就是由于对location URI部分和alias部分最后加不加“/”犯糊涂导致的,
或者说是不清楚这种情况下最终代理到什么path导致的。

// case1
location /static/case/ {
    alias E:/static/case/;
    autoindex on;
}
// case2
location /static/case {
    alias E:/static/case/;
    autoindex on;
}
case3
location /static/case/ {
    alias E:/static/case;
    autoindex on;
}
case4
location /static/case {
    alias E:/static/case;
    autoindex on;
}

以上四种情况,浏览器输入:http://127.0.0.1/static/case/... 只有第三种失败。
如果在这四种情况的location前面都加上 ^~ 结果也是一样的,因为 ^~ 和[space]都是前缀匹配。

**最终代理路径是: alias路径 + location部分URI和浏览器输入的URL未匹配到的部分。
这个路径下有文件,就200,没有文件,就404。**
所以分析一下为什么第三种写法不能正确代理呢,
浏览器URL: http://127.0.0.1/static/case/...
location:/static/case/,
因此两个URL匹配部分是/static/case/,
未匹配部分是c.js。
因此它最终代理的path是:E:/static/case + c.js = E:/static/casec.js,相当于找static目录下有没有casec.js文件,因为没这个文件,所以404。

location是正则匹配~, ~*时
    location ~ /static/case/ {
        alias E:/static/case/;
        autoindex on;
    }

浏览器URL1:http://127.0.0.1/static/case/...
浏览器URL2:http://127.0.0.1/static/case/...
浏览器URL3:http://127.0.0.1/static/case/...
浏览器URL4:http://127.0.0.1/static/case/,
结果都是一样的,返回/static/case目录。
其中只有URL4,直接200返回。URL1-3都是301->200。

重定向不是无限的,当浏览器URL case后的层级大于10时,就不再301->200,而是直接200返回。
即,浏览器URL5,直接200返回。代理到/static/case目录。
浏览器URL5:http://127.0.0.1/static/case/...

因此,代理目录时,location还是正则匹配的话,是无法访问到这个目录下的各个文件的。

解决办法有两个。

    关于既想用~又想能代理到某目录下各个文件的解决办法:
    //方案1
    location ~ ^/(.+)/(.+)/(.+\.js)$ {
        alias E:/static/case/$3;
    }
    //方案2、用root结合rewrite代替
    location ~ ^/.+/.+/.+\.js$ {
        root E:/;
        rewrite ^/(.*) /$1 break;
    }

飞叶_前端
1.4k 声望139 粉丝

Wasm和emscripten技术交流群:939206522